//! # Executor
//!
//! 定义 runtime 执行器模块
//!
//!
//!
//!
mod execute;
pub use execute::*;

pub mod event;
pub use event::*;

mod owner;
pub use owner::*;

mod state;
pub use state::*;

use crate::pkg::Delegate;

use sgs_core::preclude::{Card, Player, Role};

/// 委托处理器
#[derive(Debug)]
pub struct Controller<'a> {
    /// 所有卡牌数据
    ///
    /// 储存的是 index
    pub state: &'a mut State,

    /// 所有的 players
    pub players: &'a mut Vec<Player>,
}

/// 数据查看器
#[derive(Debug)]
pub struct Viewer<'a> {
    /// 拥有所有的卡组
    ///
    /// 该卡组引用于 Loader 中的 cards
    pub cards: &'a Vec<Card>,

    pub roles: &'a Vec<Role>,

    /// 唯一包标识符
    pub tag: &'a String,

    /// 包名称
    pub pkg_name: &'a String,

    /// 模式名称
    pub pattern_name: &'a String,

    /// 包版本号
    pub version: &'a String,

    /// 描述（可选）
    pub desp: &'a String,

    /// 任务执行器列表
    pub delegators: &'a Vec<Box<dyn Delegate>>,
}

/// Executor
///
/// runtime 执行器
///
/// 需要先设置当前运行时包编号进行初始化
///
#[derive(Debug)]
pub struct Executor<'a> {
    /// 唯一标识符
    pub tag: &'a String,

    /// 包名称
    pub pkg_name: &'a String,

    /// 模式名称
    pub pattern_name: &'a String,

    /// 版本号
    pub version: &'a String,

    /// 描述（可选）
    pub desp: &'a String,

    pub roles: &'a Vec<Role>,

    /// 拥有所有的卡组
    ///
    /// 该卡组引用于 Loader 中的 cards
    pub cards: &'a Vec<Card>,

    /// 任务执行器列表
    pub delegators: &'a Vec<Box<dyn Delegate>>,

    /// 所有卡牌数据
    ///
    /// 储存的是 index
    pub state: State,

    /// 所有的 players
    ///
    pub players: Vec<Player>,
}

/// 生命周期事件分发
macro_rules! lifecycle_event {
    ($event:ident => $exc:expr, $viewer:expr, $ctrl:expr) => {{
        for delegator in $exc.delegators {
            delegator.delegate(&LifeCycle::$event.into(), &$viewer, &mut $ctrl);
        }
    }};
}

impl<'a> Executor<'a> {
    /// 创建事件栈
    ///
    /// 开始事件循环
    pub fn setup(&mut self) {
        let mut event_stack = Event::init_stack();

        let viewer = Viewer {
            tag: &self.tag,
            desp: &self.desp,
            cards: &self.cards,
            roles: &self.roles,
            version: &self.version,
            pkg_name: &self.pkg_name,
            delegators: &self.delegators,
            pattern_name: &self.pattern_name,
        };

        let mut controller = Controller {
            state: &mut self.state,
            players: &mut self.players,
        };

        loop {
            lifecycle_event!(Start => self, viewer, controller);

            let event = match event_stack.pop() {
                Some(event) if !event.is_stop() => event,
                _ => {
                    lifecycle_event!(Stop => self, viewer, controller);
                    break;
                }
            };

            lifecycle_event!(Seek => self, viewer, controller);

            for delegator in self.delegators {
                if let Some(event) = delegator.delegate(&event, &viewer, &mut controller) {
                    lifecycle_event!(Doing => self, viewer, controller);
                    event_stack.push(event);
                    lifecycle_event!(Done => self, viewer, controller);
                    break;
                }
            }

            lifecycle_event!(Complete => self, viewer, controller);
        }
    }
}
